﻿using Common.ConfigurationOptions;
using IdentityServer4.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

namespace Identity
{
    public static partial class ServiceExtensions
    {
        public static IIdentityServerBuilder AddIdentityServer4(this IServiceCollection services, IConfiguration configuration)
        {

            var configurationDBPosition = "IdentityServer:DBs:ConfigurationDB";
            var configurationDBOptions = configuration.GetSection(configurationDBPosition)
                                         .Get<DbConfigOption>();

            var operationDBPosition = "IdentityServer:DBs:OperationDB";
            var operationDBOptions = configuration.GetSection(operationDBPosition)
                                         .Get<DbConfigOption>();

            var userInteractionOptionPosition = "IdentityServer:UserInteraction";
            var userInteractionOption = configuration.GetSection(userInteractionOptionPosition)
                                         .Get<UserInteractionOptions>();
            var authenticationOption = configuration.GetSection(AuthenticationOption.Position).Get<AuthenticationOption>();
            if (authenticationOption is null)
            {
                throw new ArgumentNullException(nameof(AuthenticationOption.Position));
            }
            return services.AddIdentityServer(options =>
                {
                    options.IssuerUri = authenticationOption.Audience;
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                    options.UserInteraction = userInteractionOption;
                }).AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = options => options.ConfigureDbContext(configurationDBOptions);
                }).AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = options => options.ConfigureDbContext(operationDBOptions);
                });
        }

        private static DbContextOptionsBuilder ConfigureDbContext(this DbContextOptionsBuilder dbContextOptions, DbConfigOption dbConfigOption)
        {
            if (string.IsNullOrWhiteSpace(dbConfigOption.Connection))
            {
                throw new ArgumentNullException(nameof(dbConfigOption.Connection));
            }
            var migrationAssembly = Assembly.GetExecutingAssembly().GetName().Name;
            switch (dbConfigOption.DataBaseType)
            {
                case DataBaseType.MSSQL:
                    dbContextOptions.UseSqlServer(dbConfigOption.Connection, action =>
                     {
                         action.MigrationsHistoryTable("MigrationHistory", "dbo");
                         action.MigrationsAssembly(migrationAssembly);
                     });
                    break;
                case DataBaseType.MySQL:
                    dbContextOptions.UseMySQL(dbConfigOption.Connection, action =>
                    {
                        action.MigrationsHistoryTable("MigrationHistory", "dbo");
                        action.MigrationsAssembly(migrationAssembly);
                    });
                    break;
                default:
                    break;
            }
            return dbContextOptions;
        }

    }
}